/*
 * The MIT License
 * Copyright (c) 2012 kc4.org
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.kc4.sso.auth;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;

import org.kc4.sso.filter.Authenticator;
import org.kc4.sso.session.SSOSessionStore;

/**
 * @author yoichi kikuchi
 *
 */
public class SSOProviderInitParameters {

	private static final String EMPTY = "";

	private static final String INIT_PARAM_NAME_SIGNON_PAGE = "SignonPage";
	private static final String INIT_PARAM_NAME_AUTHENTICATOR = "Authenticator";
	private static final String INIT_PARAM_NAME_SSO_SESSION_STORE = "SSOSessionStore";
	private static final String INIT_PARAM_NAME_WHITE_CLIENTS = "WhiteClients";

	private String signonPage = EMPTY;
	private Authenticator authenticator;
	private SSOSessionStore ssoSessionStore;
	private String[] whiteClients = new String[0];

	private static SSOProviderInitParameters instance;

	/**
	 * {@link SSOProviderInitParameters} インスタンスを取得します。
	 *
	 * @return {@link SSOProviderInitParameters} インスタンス。
	 */
	public static SSOProviderInitParameters getInstance() {

		return getInstance(null);
	}

	/**
	 * {@link SSOProviderInitParameters} インスタンスを取得します。
	 *
	 * @param params マッピングされたパラメーター。
	 * @return {@link SSOProviderInitParameters} インスタンス。
	 */
	public static SSOProviderInitParameters getInstance(Map<String, String> params) {

		if (instance == null) {

			try {

				instance = new SSOProviderInitParameters(params);
			}
			catch (ServletException e) {

				throw new IllegalStateException(e);
			}
		}

		return instance;
	}

	/**
	 * インスタンスを生成し、{@link Map} からパラメーターを読み込みます。
	 *
	 * @param params マッピングされたパラメーター。
	 * @throws ServletException サーブレット例外。
	 */
	@SuppressWarnings("unchecked")
	protected SSOProviderInitParameters(Map<String, String> params) throws ServletException {

		if (params == null) {

			return;
		}

		// サインオンページの取得
		this.setSignonPage(params.get(INIT_PARAM_NAME_SIGNON_PAGE));

		try {

			String authClassName = params.get(INIT_PARAM_NAME_AUTHENTICATOR);
			Class<? extends Authenticator> authClass =
				(Class<? extends Authenticator>) Class.forName(authClassName);

			this.setAuthenticator(authClass.newInstance());
		}
		catch (Exception e) {

			throw new ServletException(e);
		}

		try {

			String storeClassName = params.get(INIT_PARAM_NAME_SSO_SESSION_STORE);
			Class<? extends SSOSessionStore> storeClass =
				(Class<? extends SSOSessionStore>) Class.forName(storeClassName);

			this.setSsoSessionStore(storeClass.newInstance());
		}
		catch (Exception e) {

			throw new ServletException(e);
		}

		// SSOクライアントとして認証利用を許可するホワイトリストを取得
		String whiteClientsString = params.get(INIT_PARAM_NAME_WHITE_CLIENTS);
		if (whiteClientsString != null) {

			List<String> whiteClients = Arrays.asList(whiteClientsString.split("\\s*,\\s*"));
			whiteClients.remove(EMPTY);
			this.setWhiteClients(whiteClients.toArray(this.getWhiteClients()));
		}
	}

	/**
	 * signonPage を取得します。
	 *
	 * @return signonPage オブジェクト。
	 */
	public String getSignonPage() {
		return this.signonPage;
	}

	/**
	 * signonPage を設定します。
	 *
	 * @param signonPage signonPage オブジェクト。
	 */
	protected void setSignonPage(String signonPage) {
		this.signonPage = signonPage;
	}

	/**
	 * authenticator を取得します。
	 *
	 * @return authenticator オブジェクト。
	 */
	public Authenticator getAuthenticator() {
		return this.authenticator;
	}

	/**
	 * authenticator を設定します。
	 *
	 * @param authenticator authenticator オブジェクト。
	 */
	protected void setAuthenticator(Authenticator authenticator) {
		this.authenticator = authenticator;
	}

	/**
	 * ssoSessionStore を取得します。
	 *
	 * @return ssoSessionStore オブジェクト。
	 */
	public SSOSessionStore getSsoSessionStore() {
		return this.ssoSessionStore;
	}

	/**
	 * ssoSessionStore を設定します。
	 *
	 * @param ssoSessionStore ssoSessionStore オブジェクト。
	 */
	protected void setSsoSessionStore(SSOSessionStore ssoSessionStore) {
		this.ssoSessionStore = ssoSessionStore;
	}

	/**
	 * whiteClients を取得します。
	 *
	 * @return whiteClients オブジェクト。
	 */
	public String[] getWhiteClients() {
		return this.whiteClients;
	}

	/**
	 * whiteClients を設定します。
	 *
	 * @param whiteClients whiteClients オブジェクト。
	 */
	protected void setWhiteClients(String[] whiteClients) {
		this.whiteClients = whiteClients;
	}
}
